<?php
class Listing extends AppModel
{
	var $name = 'Listing';
	Const PUBLISH = 1;
	Const UNPUBLISH = 0;
	
	var $scopes = array(
		'published' => array('Listing.status'=>self::PUBLISH)
	);	
	
	var $hasMany = array(
					'Review'=>array(
						'dependent'=>true,   
					),
					'ListingAsset'=>array(
						'className'=>'ListingAsset',
						'foreignKey'=>'listing_id',
						'dependent'=>true,						
					),
	);
		
	var $belongsTo = array(
						'ListCategory'=>array(
								'className'=>'ListCategory',
								'foreignKey'=>'list_category_id',
								),
						'User'=>array(
								'className'=>'Users.User',
								'foreignKey'=>'user_id',								
								'counterCache'=>true,
								'counterScope'=>array('Listing.status'=>self::PUBLISH)
								)
							);
	var $actsAs = array(
					'Assets.MultiUpload' => array(
							"type"=>"hasMany",
							"uploadModelName"=>"ListingAsset"),
					'Feature'=>array('limit'=>null),
					'Users.UserContent' => array(
							'badwordFilter' => true, 
							'fieldsToFilter' => array('title','description'),
							'posterModels'=>array('Users.User'=>array('dependent'=>true))	
					),
					'Cms.Sluggable'=>array('overwrite'=>true),
					'Containable',
					'Cms.Metric' => array(
										array('metric' => 'NumRecords')
									),
					'Tags.Taggable'=>array(
							'deleteExisting'=>true
									),
					'AutoModerator.AutoModerator'=> array()       
				);	
					
	var $fieldProperties = array(
              'additional_categories'=> array(),
							'title'=>array(
									'label'=>'Title',
									'group'=>array('add','edit','view'),
									'type'=>"text",
									),
							'status'=>array(
									'group'=>array('add','edit'),
									'type'=>'hidden',
									'options'=>array('0','1'),									
									),							
							'description'=>array(
									'label'=>'Description',
									'type'=>'editor',
									'group'=>array('add','edit')
									),
							'asset_inputs' => array(
								'type'=>"parent",
								'childInfo' => array(
									'model'=>"ListingAsset",
									'allowEdit' => false,
									'child_group' => "add",
									'allowMultiple' => true,
									'deleteMissing' => false,
								),
								'fieldset' => false,
							),
						);
						
	var $validate = array(
					
					'title'=>array(
						'notEmpty'=>array(
								'rule'=>VALID_NOT_EMPTY,
								'message'=>'Title can\'t be blank.'
								)
					),
					
					'list_category_id'=>array(
							'rule'=>VALID_NOT_EMPTY,
							'message'=>'Please select a category.'),
	);
						
	var $additionalFields = array(
								'uploadedFile',
								'image',
								'viewUrl',
								'userAvg',
								'editorialAvg',
								'editorReviewCount','ownerName','category_list');
	
	var $cacheFields = array(
							'userAvg'=>"onUpdate",
							'editorialAvg'=>"onUpdate",
							//'image'=>"+2 minutes",
							'editorReviewCount'=>"onUpdate",
							'ownerName'=>"onUpdate",
							'category_list' => "onUpdate"
						);
	var $categoryId = null;	
	var $cachedFieldProperties = array();
	
	function editorReviewCount($result)
	{
		if(!isset($result[$this->alias]['id']))
		{
			return ;
		}
		$listingId = $result[$this->alias]['id'];
		$editorReviewCount = $this->Review->find('count',array('conditions'=>array('Review.listing_id'=>$listingId,'Review.status'=>Review::PUBLISHED,'Review.is_editorial'=>1)));
		return $editorReviewCount;
	}	
	function image($result)
	{	
		$image = '/uploads/listing_image.gif';
		$useDefault = false;
		if(!empty($result)  &&  isset($result['Listing']['uploadedFile']) && !empty($result['Listing']['uploadedFile']))
		{
			//This can be a performance bottleneck.
			if(AppUtility::allowPaidListing())
			{
				$EffectivePlan = cri("PaidListings.ListingPlan")->getEffectivePlan($result['Listing']['id']);
				if($EffectivePlan->limitImages()  && $EffectivePlan->getAllowedTotalImagesCount() < 1 )
				{
					$useDefault = true;
				}
			}
			if($useDefault == false)
			{
				$image = '/uploads/listing_assets/'.$result['Listing']['uploadedFile'];
			}
		}
		return $image;
	}
	
	function viewUrl($result)
	{
		$url = '/listings/view/'.$result['Listing']['slug'];
		return $url;	
		
	}
	
	function getAttributes($result = null,$refresh = false)
	{	
		if(!class_exists('Fieldset'))
		{
			App::import('Model','Eav.Fieldset');
		}
		$customFields = array();
		if($result && isset($result['Listing']['category_list']))
		{
			if(count($result['Listing']['category_list']) > 0)
			{
				$this->categoryId = $result['Listing']['category_list'];
			}else
			{
				$this->categoryId = array($result['Listing']['list_category_id']);
			}
		}
		if($this->categoryId && !is_array($this->categoryId))
		{
			$this->categoryId = array($this->categoryId);
		}else if(!$this->categoryId)
		{
			$this->categoryId = array();
		}
		foreach($this->categoryId as $categoryId)
		{
			$categoryCustomFields = $this->ListCategory->getCustomFields($categoryId,Fieldset::TYPE_LISTING);
			$customFields = am($customFields,$categoryCustomFields);
		}
		//@todo review me	
		if(AppUtility::allowPaidListing() && isset($this->currentPlanInfo) && $this->currentPlanInfo)
		{
			$retrictFields = true;
			if(is_object($this->currentPlanInfo) && $this->currentPlanInfo instanceof EffectiveListingPlan)
			{
				if($this->currentPlanInfo->restrictFields())
				{
				  $allowedFielsets = $this->currentPlanInfo->getFieldsets();
				  $allowedCustomFields = $this->currentPlanInfo->getCustomFields();
				}else
				{
				  $retrictFields = false;
				}
			}else
			{
				$allowedFielsets = $this->currentPlanInfo['Plan']['custom_fields']['fieldsets'];
				$allowedCustomFields = $this->currentPlanInfo['Plan']['custom_fields']['fields'];
			}
			if($retrictFields)
			{
			  foreach($customFields as $name => $customField)
			  {
				  if(isset($customField['fieldset_id']) && (!in_array($customField['fieldset_id'],$allowedFielsets) && !in_array($customField['custom_field_id'],$allowedCustomFields)))
				  {
					  unset($customFields[$name]);
				  }
			  }                  
			}

		}
		$searchField = cr('MapConfig.search_field');
		//add custom field only if it's present in customfields.Else creates problem in schema array.
		if($searchField && cr("MapConfig.show_distance") && isset($customFields[$searchField]))
		{
			if(!isset($customFields[$searchField]))
			{
				$customFields[$searchField] = array();
			}
			$customFields[$searchField]['advanced_search'] ='1';
			$customFields[$searchField]['search_type'] = "geo"; 
		}
		if(!class_exists('ListingFieldProperties'))
		{
		  App::import("Vendor","ListingFieldProperties");
		}
		return new ListingFieldProperties($customFields);
	}
	
	/**
	 * PlanId is used for Add and Edit Purpose only.
	 */
	function setCategory($categoryIds = null,$currentPlanInfo = null)
	{
		$this->categoryId = $categoryIds;
		$this->currentPlanInfo = $currentPlanInfo;
		$this->refreshFieldProperties();
		unset($this->_distinctFieldTypes);
		GigaFieldTypesHandler::trigger($this->getDistinctFieldTypes(), 'onModelInitialize', array($this));
	}
		
	function beforeSave($options = array())
	{
		if(isset($this->data['Listing']['user_id']) && !empty($this->data['Listing']['user_id']))
		{
			$isEditor = $this->User->isEditor($this->data['Listing']['user_id']);
			if($isEditor)
			{
				$this->data['Listing']['is_editorial'] = 1;
			}
		}
		if(isset($this->data[$this->alias]['title']))
		{
			$this->data[$this->alias]['title'] = trim($this->data[$this->alias]['title']);
		}
		//@todo (1.1) $this->data['Listing']['id']==''
		if(cr("ListingConfig.enable_moderation") == false && (!isset($this->data['Listing']['id']) || empty($this->data['Listing']['id'])))
		{
			$this->data['Listing']['status'] = self::PUBLISH;
		}
		return parent::beforeSave($options);
	}
	
	function getReviewAttributes($id)
	{
		$categoryId = $this->field('list_category_id',array($this->alias.'.id'=>$id));
		$fields = $this->ListCategory->getCustomFields($categoryId,$this->Review->alias);
		return $fields;
	}	
	//@todo (1.1) : remove cache call we will be using Event listener instead.
	function afterSave($created)
	{
		if(isset($this->data[$this->alias]['status']))
		{
			cri('Modules.Module')->clearModuleSpecificCache('CategoryList');
			$this->ListCategory->clearCaheForListing($this->categoryId);
			GigaCache::delete('home_categories');
		}
		parent::afterSave($created);
	}

	//@TODO (1.1) : remove cache call we will be using Event listener instead.
	function afterDelete()
	{
		cri('Modules.Module')->clearModuleSpecificCache('CategoryList');
		GigaCache::delete('home_categories');
		parent::afterDelete();		
	}
	
	function beforeDelete($cascade)
	{
		$this->ListCategory->clearCaheForListing($this->categoryId);
		return parent::beforeDelete($cascade);
	}
	
	//function _getListingCategory
	
	function getNewListing($limit=10,$catgeoryId=null)
	{
		$conditions = array($this->alias.'.status'=>self::PUBLISH);
		if($catgeoryId)
		{
			$conditions["$this->alias.list_category_id"] = $catgeoryId; 
		}
		$order = array("$this->alias.created desc");
		$recursive = 0;
		$contain = array('ListCategory');
		return $this->find('all',compact('conditions','recursive','contain','order','limit'));
	}
	/**
	 * Avreage rating for a listing only of non editorl review.
	 * @param unknown_type $listingId
	 */
	function saveRatingAverages($listingId)
	{
		$categoryId = $this->field('list_category_id',array('Listing.id'=>$listingId));
		$this->setCategory($categoryId);
		$FieldPropertyObject = $this->getAttributes();
		$ratableFields = $FieldPropertyObject->getFields('type',SCHEMA_TYPE_RATING);
		$this->Review->setCategoryId($categoryId);
		$reviwes = $this->Review->find('all',array('conditions'=>array('Review.status'=>Review::PUBLISHED,'Review.listing_id'=>$listingId,'NOT'=>array('Review.is_editorial'=>Review::EDITORIAL)),'recursive'=>-1));
		$ratingsData = array();
		foreach($ratableFields as $field)
		{
			$ratings = Set::extract("{n}.".$this->Review->alias.".$field",$reviwes);
			
			$ratings = Set::filter($ratings);
			if(!is_array($ratings) || count($ratings) == 0)
			{
				$value = 0;
			}else
			{
				$value = array_sum($ratings)/count($ratings);
			}
			$ratingsData[$field] = $value;
		}
		if($ratingsData)
		{
			$this->create();
			$this->id = $listingId;
			$data = array($this->alias=>$ratingsData);
			$data[$this->alias]['id'] = $listingId;
			$this->save($data,false);
			$this->clearRecordCache($listingId);
		}else
		{
			$this->clearRecordCache($listingId);
		}
		
	}
	
	function userAvg($result)
	{
		$value = false;
		$noField = false;
		if(isset($result[$this->alias]['list_category_id']))
		{
			$ratableFields = $this->getAttributes($result)->getFields('type',SCHEMA_TYPE_RATING);
			foreach($ratableFields as $ratableField)
			{
				if(isset($result[$this->alias][$ratableField]))
				{
					if($value === false)
					{
						$value = 0;
					}
					$value += 	$result[$this->alias][$ratableField];
				}else
				{
					$noField = true;
					break;
				}
			}
			if($value!==false && count($ratableFields) > 0)
			{
				$value = $value/count($ratableFields);
			}
		}
		//no save if eav field was not present in data.
		if($noField == true)
		{
			return false;
		}
		return number_format($value,1);
	}
	
	function editorialAvg($result)
	{
		$value = 0;
		$this->Review->recursive = -1;
		$review = $this->Review->find('first',array('conditions'=>array($this->Review->alias.'.listing_id'=>$result['Listing']['id'],$this->Review->alias.'.is_editorial'=>Review::EDITORIAL,$this->Review->alias.'.status'=>Review::PUBLISHED)));
		if(isset($review[$this->Review->alias]['avg_score']))
		{
			$value= $review[$this->Review->alias]['avg_score'];
		}
		return number_format($value,1);
	}
	
	function getSearchFields($categoryId)
	{
		$this->setCategory($categoryId);
		$fields =  $this->getFields('advanced_search',1);
		return $fields;
	}
	
	function getTextSearchCondition($keyword,$and = true)
	{
		
		$like= false;
		$bol = "OR";
		if($and)
		{
			$bol = "AND";
		}
		if(strlen($keyword) <= 3)
		{
			$condition['OR'] = array('Listing.title like'=>"%$keyword%");
		}else
		{
					
			foreach(explode(" ",$keyword) as $kword)
			{
				$kword = trim($kword);
				if(strlen($kword) == 0)
				{
					continue;
				}
				$kword = mysql_real_escape_string($kword);
				$condition[$bol][] = 'Listing.title like "%'.$kword.'%"';
			}
		}
		return $condition;
	}
	
	function afterInitialize()
	{
		if (cr("ListingConfig.allow_multiple_categories")) 
		{
			$this->bindModel(array(
				'hasMany' => array(
					'AdditionalCategory' => array(
						'dependent' => true
					),
				),
					), false);
			$this->setFieldProperties("additional_categories", array('label' => "Categories", 'type' => "parent", 'fieldset' => false,
            'childInfo' => array('model' => "AdditionalCategory",
                'allowEdit' => true,
                'child_group' => "child_add",
                'allowMultiple' => true,
                'deleteMissing' => true,
            ),
            'addMoreLabel' => "Add more category",));
		}
		$this->setFieldProperties("category_list", array("fieldModifier"=>"toggleSerialized"));
		$addresses = array();
		if(cr("MapConfig.address1_field"))
		{
			$addresses[] = cr("MapConfig.address1_field");
		}
		if(cr("MapConfig.address2_field"))
		{
			$addresses[] = cr("MapConfig.address2_field");
		}
		//@GEOMAP INTERSECTION.
		$behaviors  = array('Geo.Geo'=>array(
					'latitude'=>"lat", 
					'longitude' => "lng",
					'address'=>$addresses,
					'getCordinatesOnSave'=>true,//(bool)cr("MapConfig.map_on_save"),
					'city'=>cr("MapConfig.city_field"),
					'state'=>cr("MapConfig.state_field"),
					'postal_code'=>cr("MapConfig.postal_code_field"),
					'country' => cr("MapConfig.postal_code_field"),
					"locationCacheField" =>'location_search_cache'),
		'Eav.Eav'=>array('dynamicRow'=>true, 'initCallback' => true,'active'=>true));
        if(cr("MapConfig.show_form_map"))
        {
          //$this->setFieldProperties("lat", array("type"=>"hidden",'group'=>array("add","edit")));
          //$this->setFieldProperties("lng", array("type"=>"hidden",'group'=>array("add","edit")));
        }
		foreach($behaviors as $behavior => $config)
		{
			$this->Behaviors->attach($behavior,$config);
		}
		$this->setFieldProperties('asset_inputs', array('addMoreLabel'=>__("Add more Images"),'label'=>__("Images"),));
		parent::afterInitialize();
		$this->cacheFields['uploadedFile'] = "onUpdate";
	}
	
	function hasDefaultImage($id)
	{
		return $this->ListingAsset->hasAny(array('is_default'=>1,'listing_id'=>$id));
	}
	
	function ownerName($listing)
	{
		$user = null;
		if($listing[$this->alias]['owner_id'])
		{
			$user = $this->User->field("username",array("id"=>$listing[$this->alias]['owner_id']));
			if(!$user)
			{
				$user = null;
			}
		}
		return $user;
	}
	
	function isOwner($listingId,$userId)
	{
		return $this->field("owner_id",array("$this->alias.id"=>$listingId)) == $userId;
	}
	
	function getFeaturedListings()
	{
		$cacheKey = "feauted_listings";
		GigaCache::set(array("duration"=>"+15 minutes",'path'=>CACHE));
		$listings = GigaCache::read($cacheKey);
		if($listings === false)
		{
			$listings = $this->find("list",array("conditions"=>array("is_featured"=>1,'status'=>Listing::PUBLISH),'recursive'=>-1,'fields'=>array("id"),'limit'=>100));
			GigaCache::set(array("duration"=>"+15 minutes",'path'=>CACHE));
			GigaCache::write($cacheKey,$listings);
		}
		return $listings;
	}
	
	function makeFeatured($id)
	{
		$params = func_get_args();
		GigaCache::set(array("duration"=>"+15 minutes",'path'=>CACHE));
		GigaCache::delete("feauted_listings");
		return $this->call__(__FUNCTION__,$params);
	}
	
	function getDefaultFields()
	{
		$classVars = get_class_vars(__CLASS__);
		$fields =  array_keys($classVars['fieldProperties']);
		$fields = array_combine($fields,$fields);
		unset($fields['asset_inputs'],$fields['additional_categories']);
		return array_values($fields);
	}
    /**
     * A workaround to delete delete existing video.
     */
    function deleteVideo($listingId,$field)
    {
        $this->recursive  = -1;
        $listing = $this->findById($listingId);
        $this->setFieldProperties($field,array("videoConfig"=>array('removeOnEmpty'=>true)));
        $this->setCategory($listing['Listing']['list_category_id']);
        $FieldPropeties = $this->getAttributes();
        if($FieldPropeties->hasField($field))
        {
          $this->saveField($field,"");
        }
    }
	
	function category_list($listing)
	{
		if(!isset($listing[$this->alias]['list_category_id']))
		{
			return false;
		}
		$categoryId = $listing[$this->alias]['list_category_id'];
		if (cr('ListingConfig.allow_multiple_categories'))
		{
			$categoryIds = cri('AdditionalCategory')->getCategoriesList($listing['Listing']['id']);
		}
		$categoryIds[] = $categoryId;
		$categoryIds = array_unique($categoryIds);
		$categoryIds = array_values($categoryIds);
		return $categoryIds;
	}
}
?>